﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Win32;
using System.IO;
using System.Xml;
using Ionic.Zip;
using RuleCode.ObjectTree;


namespace VSOTreeInstaller
{
    [RunInstaller(true)]
    public partial class VSObjectTreeInstaller : Installer
    {
        static string CryKey = RuleCode.ObjectTree.Util.CryKey;

        #region 构造方法
        public VSObjectTreeInstaller()
        {
            InitializeComponent();
        }
        #endregion

        #region 安装
        public override void Install(IDictionary stateSaver)
        {
            try
            {
                bool hasFoundVs2008 =false ;
                string devenvExeName =string.Empty ;
                string visualStudioRegKeyPath = @"SOFTWARE\Microsoft\VisualStudio\";
                string vs2008 = visualStudioRegKeyPath +"9.0";
                RegistryKey vs2008Key = Registry.LocalMachine.OpenSubKey(vs2008);
                if (vs2008Key != null && vs2008Key.GetValue("InstallDir")!=null)
                {
                    string vsInstallDir = vs2008Key.GetValue("InstallDir").ToString().TrimEnd("\\".ToCharArray ()) +"\\";
                    devenvExeName = vsInstallDir + "devenv.exe";
                    hasFoundVs2008 = File.Exists(devenvExeName);
                    vs2008Key.Close(); 
                }
               
                if(!hasFoundVs2008 )     
                    throw new Exception("当前插件只针对Visual Studio 2008有效，请在安装Visual Studio 2008 后再安装该插件！");  

                string setupFilePath = Context.Parameters["targetDir"];
                if (String.IsNullOrEmpty(setupFilePath))         
                    throw new Exception("安装失败，没有找到安装路径！");      

                string addInFileName = "VSObjectTreeAddIn.AddIn";
                string addInFullName = setupFilePath + addInFileName;
                if (!File.Exists(addInFullName))         
                    throw new Exception("安装失败，没有找到插件路径！");   

                //判断是否存在 运行中的devenv.exe,如果存在，则关闭！
                Process[] allProcess = Process.GetProcessesByName("devenv");
                if (allProcess.Length > 0)
                {
                    if(MessageBox.Show ("安装插件需要关闭Visual Studio 应用程序，\n是否强制关闭正在运行Visual Studio？","关闭正在使用的devenv.exe", MessageBoxButtons.OKCancel ) != DialogResult.OK )  
                        throw new Exception("安装失败！\n请在关闭 Visual Studio之后再次安装！");

                    allProcess = Process.GetProcessesByName("devenv");
                    foreach (Process p in allProcess)
                        p.Kill();
                }

                //创建 info.xml 
                string infoFileName = Path.Combine (setupFilePath ,"info.xml");
                
                //FileInfo fInfo = new FileInfo(infoFileName);
                //fInfo.Attributes =  fInfo.Attributes;
                

                RuleCode.Common.Cryptography cry = new RuleCode.Common.Cryptography();
                XmlDocument infoXmlDoc = new XmlDocument();
                XmlNode infoNode = infoXmlDoc.CreateElement("info");
                XmlNode sDateNode = infoXmlDoc.CreateElement("sdate");
                string setupdateStr = cry.DesEncrypt(DateTime.Now.ToString (), CryKey);
                sDateNode.InnerText  = setupdateStr;
                infoNode.AppendChild(sDateNode);

                XmlNode lDateNode = infoXmlDoc.CreateElement("ldate");
                lDateNode.InnerText = setupdateStr;
                infoNode.AppendChild(lDateNode);                

                XmlNode vDayNode = infoXmlDoc.CreateElement("vday");  
                string validateDays = cry.DesEncrypt("30", CryKey );
                vDayNode.InnerText = validateDays;
                infoNode.AppendChild(vDayNode);

                infoXmlDoc.AppendChild(infoNode);

                if (File.Exists(infoFileName))
                    File.Delete (infoFileName);
                infoXmlDoc.Save(infoFileName);
                
                
               



                //移动AddIn插件Xml文件，并且做修改
                string Vs2008DocumentPath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Visual Studio 2008\\Addins";
                string targetFullName = Vs2008DocumentPath + "\\" + addInFileName;
                CopyFile (addInFullName, targetFullName);
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(targetFullName);
                XmlNodeList assNodes = xmlDoc.GetElementsByTagName ("Assembly");
                if (assNodes.Count <=0)       
                    throw new Exception("安装失败，插件Xml文件错误！");
                XmlNode assNode = assNodes[0];
                assNode.InnerText = setupFilePath + "Project1.dll"; 
                xmlDoc.Save(targetFullName);


                string applicationDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                string sharpERPPath = applicationDataPath + "\\" + Util.ApplicationName + "\\";
                if (!Directory.Exists(sharpERPPath))
                    Directory.CreateDirectory(sharpERPPath);

                string aotsPath = sharpERPPath + "AOTS\\";
                if (!Directory.Exists(aotsPath))
                    Directory.CreateDirectory(aotsPath);
                
                

                //拷贝文件                                      
                string setupDataFilePath = setupFilePath + "Data\\";

                //拷贝config.XML  
                CopyFile(setupDataFilePath + "config.xml", sharpERPPath + "config.xml");
                //拷贝solutions.xml  
                CopyFile(setupDataFilePath + "solutions.xml", sharpERPPath + "solutions.xml");
                //拷贝profiles.xml 
                CopyFile(setupDataFilePath + "profiles.xml", sharpERPPath + "profiles.xml");


                //制作Default默认设置
                string defaultConfigPath = Path.Combine(aotsPath, "Default");
                if (!Directory.Exists(defaultConfigPath))
                    Directory.CreateDirectory(defaultConfigPath);
                string devAreaPath = Path.Combine (defaultConfigPath ,Util.DevArea );
                if (!Directory.Exists(devAreaPath))
                    Directory.CreateDirectory(devAreaPath);
                string objDataPath = Path.Combine(devAreaPath, GlobalStaticDirectoryPath.ObjectData.Trim("\\".ToCharArray()));
                if (!Directory.Exists(objDataPath))
                    Directory.CreateDirectory(objDataPath);
                string geneTemplatePath = Path.Combine(devAreaPath, GlobalStaticDirectoryPath.Templates.Trim ("\\".ToCharArray ()));
                if (!Directory.Exists(geneTemplatePath))
                    Directory.CreateDirectory(geneTemplatePath);
                string labelFilePath = Path.Combine(devAreaPath, GlobalStaticDirectoryPath.LabelFile.Trim ("\\".ToCharArray ()));
                if (!Directory.Exists(labelFilePath))
                    Directory.CreateDirectory(labelFilePath);

                //解压代码生成模板
                string sourceGeneTemplateZipFileName = Path.Combine(setupDataFilePath, "Templates.zip");
                using (ZipFile geneTemplateZip = ZipFile.Read(sourceGeneTemplateZipFileName))
                {
                    foreach (ZipEntry entry in geneTemplateZip)
                        entry.Extract(devAreaPath, ExtractExistingFileAction.OverwriteSilently );
                }
                //解压LabelFile文件

                string sourceLabelFileZipFileName = Path.Combine(setupDataFilePath, "LabelFile.zip");
                using (ZipFile labelFileZip = ZipFile.Read(sourceLabelFileZipFileName))
                {
                    foreach (ZipEntry entry in labelFileZip)
                        entry.Extract(devAreaPath, ExtractExistingFileAction.OverwriteSilently);
                }

                //更改 config.xml 文件 中的 插件的安装路径
                XmlDocument configXml = new XmlDocument();
                configXml.Load(sharpERPPath + "config.xml");
                XmlNode setupNode = configXml.SelectSingleNode("//setuppath");
                if (setupNode != null)
                    setupNode.InnerText = setupFilePath;
                else
                {
                    XmlNode rootNode = configXml.SelectSingleNode("//config");
                    if (rootNode == null)
                    {
                        rootNode = configXml.CreateElement("config");
                        XmlNode currentProfileNameNode = configXml.CreateElement("currentprofilename");
                        currentProfileNameNode.InnerText = "Default";
                        rootNode.AppendChild(currentProfileNameNode);
                        configXml.AppendChild(rootNode);
                    }
                    setupNode = configXml.CreateElement("setuppath");
                    setupNode.InnerText = setupFilePath;
                    rootNode.AppendChild(setupNode);
                }
                configXml.Save(sharpERPPath + "config.xml");

                

                //解压项目模板
                string projectTemplateName = "ProjectTemplates.zip";
                string sourceTemplatePath = setupFilePath;
                ZipFile zipFile = ZipFile.Read(setupDataFilePath + projectTemplateName);
                foreach (ZipEntry zipEntry in zipFile)
                {
                    zipEntry.Extract(setupFilePath, ExtractExistingFileAction.OverwriteSilently);
                }


                //运行devenv.exe /setup
                Process setupDevenvProcess =  Process.Start (devenvExeName ," /setup");
                if(setupDevenvProcess !=null)
                    setupDevenvProcess.WaitForExit ();
                setupDevenvProcess.Close ();

                

                

            }
            catch (Exception error)
            {         
                MessageBox.Show("安装失败！\n"+error .Message );
                this.Context.LogMessage(error.Message);
                return;
            }

            base.Install(stateSaver);
        }
        #endregion

        #region 卸载
        public override void Uninstall(IDictionary savedState)
        {
            //MessageBox.Show("dafdsf");
            DeleteRelativeFiles(true );
            base.Uninstall(savedState);
        }
        #endregion

        #region 回滚
        public override void Rollback(IDictionary savedState)
        {
            DeleteRelativeFiles(false ); 
            base.Rollback(savedState);
        }
        #endregion

        #region 辅助方法
        /// <summary>
        /// 拷贝文件，如果不存在目标文件，则创建目标文件
        /// </summary>
        /// <param name="soureFileName"></param>
        /// <param name="targetFileName"></param>
        protected void CopyFile(string soureFileName, string targetFileName)
        {
            if (!File.Exists(soureFileName))
                throw new Exception("没有找到源文件:"+soureFileName );
            if (File.Exists(targetFileName))
                File.Delete(targetFileName);
            File.Copy(soureFileName, targetFileName, true);
        }

        /// <summary>
        /// 当卸载和回滚的时候调用
        /// 删除配置文件和插件文件
        /// </summary>
        protected void DeleteRelativeFiles(bool isUninstall)
        {
            try
            {
                string addInFileName = "VSObjectTreeAddIn.AddIn";
                string Vs2008DocumentPath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Visual Studio 2008\\Addins";
                string targetFullName = Vs2008DocumentPath + "\\" + addInFileName;
                if (File.Exists(targetFullName))
                    File.Delete(targetFullName);

                

                string setupPath = this.Context.Parameters["targetDir"];
                if (!string.IsNullOrEmpty(setupPath) && Directory .Exists (setupPath ))
                {
                    Directory.Delete(setupPath, true);
                }

                if (isUninstall && MessageBox.Show("是否要删除配置文件和对象树属性文件？", "删除", MessageBoxButtons.OKCancel) == DialogResult.OK)
                {
                    string applicationDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                    string sharpERPPath = applicationDataPath + "\\" + Util.ApplicationName + "\\";
                    if (Directory.Exists(sharpERPPath))
                        Directory.Delete(sharpERPPath, true);
                }
            }
            catch (Exception error)
            {
                this.Context.LogMessage(error.Message);
            }
        }
        #endregion
    }
}
